#ifndef ERP_MACRO_DEFINE_H
#define ERP_MACRO_DEFINE_H

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <sstream>

namespace erp
{
namespace comm
{
/**
 * 对Vector、Set等容器中的整型或字符串进行Join分隔符转为字符串操作
 */
template<typename C>
std::string Join(const C& oContainer, const std::string strSeparator)
{
	std::stringstream ssBuffer;
	for (typename C::const_iterator it = oContainer.begin();
			it != oContainer.end(); it++)
	{
		if (it != oContainer.begin())
		{
			ssBuffer << strSeparator;
		}
		ssBuffer << *it;
	}
	return ssBuffer.str();
}
/**
*
* 取服务cont_config.xml配置项宏
*/
#define GetStringConfig(Config)do{\
    int iRetCode=0;\
    std::string strTemp;;\
    iRetCode=pCntl->getConfig(#Config, strTemp);\
    if(iRetCode!=0)\
    {\
        std::cout<<#Config<<"="<<str##Config<<" =default="<<std::endl;\
    }\
    else\
    {\
        str##Config=strTemp;\
        std::cout<<#Config<<"="<<str##Config<<std::endl;\
    }\
}while(0)

#define GetUintConfig(Config)do{\
    int iRetCode=0;\
    uint32_t dwTemp=0;\
    iRetCode=pCntl->getConfig(#Config, dwTemp);\
    if(iRetCode!=0)\
    {\
        std::cout<<#Config<<"="<<dw##Config<<" =default="<<std::endl;\
    }\
    else\
    {\
        dw##Config=dwTemp;\
        std::cout<<#Config<<"="<<dw##Config<<std::endl;\
    }\
}while(0)

#define GetUintConfig2(Config, Value)do{\
	int iRetCode=0;\
	uint32_t dwTemp=0;\
	iRetCode=pCntl->getConfig(#Config#Value, dwTemp);\
	if(iRetCode!=0)\
	{\
		std::cout<<#Config#Value<<"="<<dw##Value<<" =default="<<std::endl;\
	}\
	else\
	{\
		dw##Value=dwTemp;\
		std::cout<<#Config#Value<<"="<<dw##Value<<std::endl;\
	}\
}while(0)

#define GetStringConfig2(Config, Value)do{\
	int iRetCode=0;\
	std::string strTemp="";\
	iRetCode=pCntl->getConfig(#Config#Value, strTemp);\
	if(iRetCode!=0)\
	{\
		std::cout<<#Config#Value<<"="<<str##Value<<" =default="<<std::endl;\
	}\
	else\
	{\
		str##Value=strTemp;\
		std::cout<<#Config#Value<<"="<<str##Value<<std::endl;\
	}\
}while(0)

/**
*
* 请求整数型IP转String宏
*/
#define IPToString(dwIP, strIP)do{\
	struct in_addr stClient;\
	memset(&stClient, 0, sizeof(struct in_addr));\
	stClient.s_addr = htonl(dwIP);\
	strIP=inet_ntoa(stClient);\
}while(0)

/**
 * 获取DB配置和连接
 */
#define CONNECT_WITH_DALSET(Storage, CmdId, Key, RoleName, TableName, UseSetId, CntlInfo, MachineKey, Source, SceneId) do{\
	IDBOperator* pDBOperator =CDAL_SET->GetDBOperator(CmdId, Key, RoleName, TableName, UseSetId);\
	if (pDBOperator == NULL)\
	{\
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DAL_CONNECT_FAILED,\
				"GetDBOperator Failed. CmdId:%u Key:%u RoleName:%s TableName:%s UseSetId:%u OpUin:%u OpUid:%lu MachineKey:%s Source:%s SceneId:%u ErrMsg:%s",\
				CntlInfo.getCmdId(), CntlInfo.getOperatorUin(),\
				RoleName, TableName, UseSetId,\
				CntlInfo.getOperatorUin(), CntlInfo.getOperatorUid(),\
				MachineKey.c_str(), Source.c_str(), SceneId,\
				CDAL_SET->getLastErrMsg());\
		return ERR_ERP_COMMON_DAL_CONNECT_FAILED;\
	}\
	Storage.SetDBOperator(pDBOperator);\
}while(0)

/**
 * 进行更新DB数据
 */
#define DB_UPDATE(Storage, Sql, RetCode, CntlInfo, MachineKey, Source, SceneId) do{\
	RetCode = Storage.Update(Sql.str());\
	if (RetCode != 0)\
	{\
		C2C_WW_LOG_ERR(RetCode, "Update Failed。 Sql:%s",Sql.str().c_str());\
		RetCode = ERR_ERP_COMMON_DB_INSERT_FAILED;\
		C2C_WW_LOG_ERR(RetCode,\
				"Update Failed. OpUin:%u OpUid:%lu MachineKey:%s Source:%s SceneId:%u ErrMsg:%s",\
				CntlInfo.getOperatorUin(), CntlInfo.getOperatorUid(),\
				MachineKey.c_str(), Source.c_str(), SceneId,\
				Storage.GetErrMsg());\
		return RetCode;\
	}\
	if (Storage.GetAffectedRows() == 0)\
	{\
		C2C_WW_LOG_ERR(RetCode, "Update Failed。 Sql:%s",Sql.str().c_str());\
		RetCode = ERR_ERP_COMMON_DB_AFFECTED_ZERO_FAILED;\
		C2C_WW_LOG_ERR(RetCode,\
				"AffectedRows Zero. OpUin:%u OpUid:%lu MachineKey:%s Source:%s SceneId:%u ErrMsg:%s",\
				CntlInfo.getOperatorUin(), CntlInfo.getOperatorUid(),\
				MachineKey.c_str(), Source.c_str(), SceneId,\
				Storage.GetErrMsg());\
		return RetCode;\
	}\
	C2C_WW_LOG(\
			"Update Passed. Sql:%s OpUin:%u OpUid:%lu MachineKey:%s Source:%s SceneId:%u",\
			Sql.str().c_str(), CntlInfo.getOperatorUin(),\
			CntlInfo.getOperatorUid(), MachineKey.c_str(),\
			Source.c_str(), SceneId);\
}while(0)

/**
 * 进行查询DB数据
 */
#define DB_SELECT(Storage, Sql) Storage.QueryForResultSet(Sql.str());

/**
 * 进行结果集错误的检查
 */
#define DB_SELECT_RS_CHECK(Rs, Storage, Sql, RetCode, CntlInfo, MachineKey, Source, SceneId) do{\
	if(!Rs.IsReady())\
	{\
		Rs.Close();\
		RetCode = ERR_ERP_COMMON_DB_SELECT_FAILED;\
		C2C_WW_LOG_ERR(RetCode, "Select Failed。 Sql:%s",Sql.str().c_str());\
		C2C_WW_LOG_ERR(RetCode,\
				"Select Failed. OpUin:%u OpUid:%lu MachineKey:%s Source:%s SceneId:%u ErrMsg:%s",\
				CntlInfo.getOperatorUin(), CntlInfo.getOperatorUid(),\
				MachineKey.c_str(), Source.c_str(), SceneId,\
				Storage.GetErrMsg());\
		return RetCode;\
	}\
	if(!Rs.First() || Rs.GetRecordCount() == 0)\
	{\
		Rs.Close();\
		RetCode = ERR_ERP_COMMON_DB_QUERY_FAILED;\
		C2C_WW_LOG_ERR(RetCode, "Query Failed。 Sql:%s",Sql.str().c_str());\
		C2C_WW_LOG_ERR(RetCode,\
				"Query Failed. RecordCount:%u OpUin:%u OpUid:%lu MachineKey:%s Source:%s SceneId:%u",\
				Rs.GetRecordCount(),CntlInfo.getOperatorUin(), CntlInfo.getOperatorUid(),\
				MachineKey.c_str(), Source.c_str(), SceneId);\
		return RetCode;\
	}\
}while(0)

/**
 * 结果集整型字段获取设置
 */
#define RS_GET_INT_FIELD(Rs, FieldName, Object) do{\
	Object.Set##FieldName(oRs.GetBigUInt(#FieldName));\
}while(0)

/**
 * 结果集整型字段获取设置，直接进行赋值
 */
#define RS_GET_INT_FIELD_VALUE(Rs, FieldName, Value) do{\
	Value=oRs.GetBigUInt(#FieldName));\
}while(0)

/**
 * 结果集字符串字段获取设置
 */
#define RS_GET_STRING_FIELD(Rs, FieldName, Object) do{\
	Object.Set##FieldName(oRs.GetString(#FieldName));\
}while(0)

/**
 * 结果集字符串字段获取设置，直接进行赋值
 */
#define RS_GET_STRING_FIELD_VALUE(Rs, FieldName, Value) do{\
	Value=oRs.GetString(#FieldName);\
}while(0)

/**
 * SQL拼写Insert语句
 */
#define SQL_INSERT_TABLE(Sql, UseSetId, Key, RoleName, TableName) do{\
	Sql << "INSERT INTO ";\
	Sql << CDAL_SET->GetTableName(UseSetId, Key, RoleName, TableName);\
	Sql << " SET ";\
}while(0)

/**
 * SQL拼写Update语句
 */
#define SQL_UPDATE_TABLE(Sql, UseSetId, Key, RoleName, TableName) do{\
	Sql << "UPDATE ";\
	Sql << CDAL_SET->GetTableName(UseSetId, Key, RoleName, TableName);\
	Sql << " SET ";\
}while(0)

/**
 * SQL拼写Select语句，需要列清字段列表，
 * 【好处】如果数据库表与预期的字段名不一致可以及时发现，例如：缺少字段，字段名写错等
 */
#define SQL_SELECT_TABLE(Sql, UseSetId, Key, RoleName, TableName, FieldList) do{\
	Sql << "SELECT "<< FieldList <<" FROM ";\
	Sql << CDAL_SET->GetTableName(UseSetId, Key, RoleName, TableName);\
	Sql << " ";\
}while(0)

/**
 * SQL拼写Select语句，使用*，
 * 【强烈建议使用SQL_SELECT_TABLE而不要使用该方式】
 */
#define SQL_SELECT_TABLE_ALL(Sql, UseSetId, Key, RoleName, TableName, FieldList) do{\
	Sql << "SELECT * FROM ";\
	Sql << CDAL_SET->GetTableName(UseSetId, Key, RoleName, TableName);\
	Sql << " ";\
}while(0)

/**
 * SQL拼写ON DUPLICATE KEY UPDATE
 */
#define SQL_DUPLICATE_UPDATE(Sql) do{\
	Sql << "ON DUPLICATE KEY UPDATE ";\
}while(0)

/**
 * SQL拼写字段赋值，复用前边已经对该字段的赋值，一般放在SQL_DUPLICATE_UPDATE后边
 */
#define SQL_SET_FIELD_BEFORE_VALUE(Sql, FieldName, Object) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "F"#FieldName"=VALUES(F"#FieldName"), ";\
	}\
}while(0)

/**
 * SQL拼写整型字段赋值，使用对象中与数据库字段同名的字段
 */
#define SQL_SET_INT_FIELD(Sql, FieldName, Object) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "F"#FieldName"=" << Object.Get##FieldName()+0 << ", ";\
	}\
}while(0)

/**
 * SQL拼写整型字段赋值，直接赋值
 */
#define SQL_SET_INT_FIELD_VALUE(Sql, FieldName, Value) do{\
	Sql << "F"#FieldName"=" << Value << ", ";\
}while(0)

/**
 * SQL拼写字符串字段赋值，使用对象中与数据库字段同名的字段
 */
#define SQL_SET_STRING_FIELD(Sql, FieldName, Object, Storage) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "F"#FieldName"='" << Storage.EscapeString(Object.Get##FieldName()) << "', ";\
	}\
}while(0)

/**
 * SQL拼写字符串字段赋值，直接赋值
 */
#define SQL_SET_STRING_FIELD_VALUE(Sql, FieldName, Value, Storage) do{\
	Sql << "F"#FieldName"='" << Storage.EscapeString(Value) << "', ";\
}while(0)

/**
 * SQL拼写属性字段赋值，使用对象中与数据库字段同名的Include和Exclude字段，注意：BitSet位长不能超过64
 */
#define SQL_SET_PROPERTY_FIELD(Sql, FieldName, Object) do{\
	if(Object.Is##FieldName##IncludeSet()||Object.Is##FieldName##ExcludeSet())\
	{\
		Sql << "F"#FieldName"=(F"#FieldName"|" << Object.Get##FieldName##Include().to_ulong() << ")&~" << Object.Get##FieldName##Exclude().to_ulong() << ", ";\
	}\
}while(0)

/**
 * SQL拼写属性字段赋值，使用对象中与数据库字段同名的Include和Exclude字段，注意：BitSet位长不能超过64
 */
#define SQL_SET_PROPERTY_FIELD_VALUE(Sql, FieldName, Value) do{\
	Sql << "F"#FieldName"=" << Value << ", ";\
}while(0)

/**
 * SQL拼写时间字段赋值当前时间
 */
#define SQL_SET_TIME_FIELD_NOW(Sql, FieldName) do{\
	Sql << "F"#FieldName"=now(), ";\
}while(0)

/**
 * SQL拼写时间字段赋值当前时间，赋值截止
 */
#define SQL_SET_TIME_FIELD_NOW_END(Sql, FieldName) do{\
	Sql << "F"#FieldName"=now() " ;\
}while(0)

/**
 * SQL拼写Where开始
 */
#define SQL_WHERE_BEGIN(Sql) do{\
	Sql << "WHERE 1=1 ";\
}while(0)

/**
 * SQL拼写整型主键Where条件
 */
#define SQL_WHERE_INT_PRIMARY(Sql, FieldName, Object) do{\
	Sql << "AND F"#FieldName"=" << Object.Get##FieldName()+0 << " ";\
}while(0)

/**
 * SQL拼写整型主键Where条件，直接赋值
 */
#define SQL_WHERE_INT_PRIMARY_VALUE(Sql, FieldName, Value) do{\
	Sql << "AND F"#FieldName"=" << Value+0 << " ";\
}while(0)

/**
 * SQL拼写集合型Where条件，ID列表
 */
#define SQL_WHERE_FIELD_SET_NAME(Sql, DbFieldName, Object, OFieldName) do{\
	if(Object.Is##OFieldName##Set())\
	{\
		Sql << "AND F"#DbFieldName" in (" << erp::comm::Join(Object.Get##OFieldName(),",") << ") ";\
	}\
}while(0)

/**
 * SQL拼写集合型Where条件，ID列表，直接赋值
 */
#define SQL_WHERE_FIELD_SET_VALUE(Sql, FieldName, IdSet) do{\
	Sql << "AND F"#FieldName" in (" << erp::comm::Join(IdSet,",") << ") ";\
}while(0)

/**
 * SQL拼写字符串主键Where条件
 */
#define SQL_WHERE_STRING_PRIMARY(Sql, FieldName, Object, Storage) do{\
	Sql << "AND F"#FieldName"='" << Storage.EscapeString(Object.Get##FieldName()) << "' ";\
}while(0)

/**
 * SQL拼写字符串主键Where条件，直接赋值
 */
#define SQL_WHERE_STRING_PRIMARY_VALUE(Sql, FieldName, Value, Storage) do{\
	Sql << "AND F"#FieldName"='" << Storage.EscapeString(Value) << "' ";\
}while(0)

/**
 * SQL拼写整型Where条件
 */
#define SQL_WHERE_INT_FIELD(Sql, FieldName, Object) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "AND F"#FieldName"=" << Object.Get##FieldName()+0 << " ";\
	}\
}while(0)

/**
 * SQL拼写整型Where条件，数据库字段和对象字段可以不同
 */
#define SQL_WHERE_INT_FIELD_NAME(Sql, DbFieldName, Object, OFieldName) do{\
	if(Object.Is##OFieldName##Set())\
	{\
		Sql << "AND F"#DbFieldName"=" << Object.Get##OFieldName()+0 << " ";\
	}\
}while(0)

/**
 * SQL拼写整型Where条件，直接赋值
 */
#define SQL_WHERE_INT_FIELD_VALUE(Sql, FieldName, Value) do{\
	Sql << "AND F"#FieldName"=" << Value+0 << " ";\
}while(0)

/**
 * SQL拼写整型Where条件，可定义运算符号>=、<=、>、<、!=等
 */
#define SQL_WHERE_INT_FIELD_OP_NAME(Sql, FieldName, Object, Operator) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "AND F"#FieldName#Operator << Object.Get##FieldName()+0 << " ";\
	}\
}while(0)

/**
 * SQL拼写整型Where条件，数据库字段和对象字段可以不同，可定义运算符号>=、<=、>、<、!=等
 */
#define SQL_WHERE_INT_FIELD_OP_NAME(Sql, DbFieldName, Object, OFieldName, Operator) do{\
	if(Object.Is##OFieldName##Set())\
	{\
		Sql << "AND F"#DbFieldName#Operator << Object.Get##OFieldName()+0 << " ";\
	}\
}while(0)

/**
 * SQL拼写整型Where条件，直接赋值，可定义运算符号>=、<=、>、<、!=等
 */
#define SQL_WHERE_INT_FIELD_OP_VALUE(Sql, FieldName, Value, Operator) do{\
	Sql << "AND F"#FieldName#Operator << Value+0 << " ";\
}while(0)

/**
 * SQL拼写字符串Where条件
 */
#define SQL_WHERE_STRING_FIELD(Sql, FieldName, Object, Storage) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "AND F"#FieldName"='" << Storage.EscapeString(Object.Get##FieldName()) << "' ";\
	}\
}while(0)

/**
 * SQL拼写字符串Where条件，数据库字段和对象字段可以不同
 */
#define SQL_WHERE_STRING_FIELD_NAME(Sql, DbFieldName, Object, OFieldName, Storage) do{\
	if(Object.Is##OFieldName##Set())\
	{\
		Sql << "AND F"#DbFieldName"='" << Storage.EscapeString(Object.Get##OFieldName()) << "' ";\
	}\
}while(0)

/**
 * SQL拼写字符串Where条件，直接赋值
 */
#define SQL_WHERE_STRING_FIELD_VALUE(Sql, FieldName, Value, Storage) do{\
	Sql << "AND F"#FieldName"='" << Storage.EscapeString(Value) << "' ";\
}while(0)fuzzy

/**
 * SQL拼写字符串Where条件，模糊匹配
 */
#define SQL_WHERE_STRING_FIELD_FUZZY(Sql, FieldName, Object, Storage) do{\
	if(Object.Is##FieldName##Set())\
	{\
		Sql << "AND F"#FieldName" Like '%" << Storage.EscapeString(Object.Get##FieldName()) << "%' ";\
	}\
}while(0)

/**
 * SQL拼写字符串Where条件，模糊匹配，数据库字段和对象字段可以不同
 */
#define SQL_WHERE_STRING_FIELD_FUZZY_NAME(Sql, DbFieldName, Object, OFieldName, Storage) do{\
	if(Object.Is##OFieldName##Set())\
	{\
		Sql << "AND F"#DbFieldName" Like '%" << Storage.EscapeString(Object.Get##OFieldName()) << "%' ";\
	}\
}while(0)

/**
 * SQL拼写字符串Where条件，模糊匹配，直接赋值
 */
#define SQL_WHERE_STRING_FIELD_FUZZY_VALUE(Sql, FieldName, Value, Storage) do{\
	Sql << "AND F"#FieldName" Like '%" << Storage.EscapeString(Value) << "%' ";\
}while(0)

/**
 * SQL拼写属性Where条件，IncludeOption：0为且的关系；1为或的关系
 */
#define SQL_WHERE_PROPERTY_FIELD_NAME(Sql, DbFieldName, Object, OFieldName, IncludeOption) do{\
	if(Object.Is##OFieldName##IncludeSet())\
	{\
		if(IncludeOption==1)\
		{\
			Sql << "AND F"#DbFieldName"&" << Object.Get##OFieldName##Include().to_ulong() << " ";\
		}\
		else\
		{\
			Sql << "AND !((F"#DbFieldName"&"\
				<< Object.Get##OFieldName##Include().to_ulong()\
				<< ")^"\
				<< Object.Get##OFieldName##Include().to_ulong()\
				<< ") ";\
		}\
	}\
	if(Object.Is##OFieldName##ExcludeSet())\
	{\
		Sql << " !(FEmployeeProperty&"<< Object.Get##OFieldName##Exclude().to_ulong() << ") ";\
	}\
}while(0)

}
}
#endif
